package com.lagou.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.lagou.constant.OrderStatusEnum;
import com.lagou.constant.RedisConstant;
import com.lagou.constant.RocketMQConstant;
import com.lagou.entity.TbItem;
import com.lagou.entity.TbOrder;
import com.lagou.enums.DelayLevelEnum;
import com.lagou.mapper.TbOrderMapper;
import com.lagou.rocketmq.producer.Producer;
import com.lagou.service.TbItemService;
import com.lagou.service.TbOrderService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.integration.redis.util.RedisLockRegistry;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.Lock;

/**
 * <p>
 * 订单信息表 服务实现类
 * </p>
 *
 * @author qjc
 * @since 2021-12-21
 */
@Service
@Slf4j
public class TbOrderServiceImpl extends ServiceImpl<TbOrderMapper, TbOrder> implements TbOrderService {

    @Autowired
    RedisLockRegistry redisLockRegistry;
    @Autowired
    RedisTemplate redisTemplate;
    @Autowired
    TbItemService itemService;
    @Autowired
    Producer producer;

    @Override
    public String createOrder(Long itemId) {
        log.info("开始下单");
        String itemStockKey = RedisConstant.ITEM_STOCK_KEY + ":" + itemId;
        // 给商品加锁
        Lock lock = redisLockRegistry.obtain(String.valueOf(itemId));
        try {
            lock.lock();
            Integer itemCount;
            Object itemStock = redisTemplate.opsForValue().get(itemStockKey);
            if (ObjectUtils.isEmpty(itemStock)) {
                TbItem item = itemService.getById(itemId);
                itemCount = item.getCount();
                redisTemplate.opsForValue().set(itemStockKey, String.valueOf(itemCount));
            } else {
                itemCount = Integer.parseInt(String.valueOf(itemStock));
            }
            if (itemCount <= 0) {
                return "库存不足，秒杀失败！";
            }
            Boolean pushMessageResult = producer.pushMessage(RocketMQConstant.ORDER_TOPIC, RocketMQConstant.CREATE_ORDER_TAG, itemId);
            if (pushMessageResult) {
                redisTemplate.opsForValue().decrement(itemStockKey);
            }
        } catch (Exception e) {
            log.error("创建订单异常", e);
            return "创建订单异常，请重新下单！";
        } finally {
            lock.unlock();
        }

        return "下单成功！";
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveOrder(long itemId) {
        TbItem item = itemService.getById(itemId);
        itemService.decrCountById(itemId);
        log.info("保存订单信息，扣减库存");

        TbOrder order = new TbOrder();
        order.setItemId(itemId);
        order.setAmount(item.getAmount());
        order.setStatus(OrderStatusEnum.WAIT_PAY.getCode());
        save(order);
        producer.pushDelayMessage(RocketMQConstant.ORDER_TOPIC, RocketMQConstant.CANCEL_ORDER_TAG, order.getId(), DelayLevelEnum.MINUTES_ONE);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long cancelOrder(long orderId) {
        TbOrder order = getById(orderId);
        order.setStatus(OrderStatusEnum.CANCEL.getCode());
        updateById(order);
        Long itemId = order.getItemId();
        log.info("订单：{}未支付，取消该订单，商品：{}恢复库存+1", orderId, itemId);
        itemService.incrCountById(itemId, 1);
        return itemId;
    }

    @Override
    public List<TbOrder> getOrderList(Long itemId, Integer status) {
        QueryWrapper<TbOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(ObjectUtils.isNotEmpty(itemId), TbOrder::getItemId, itemId)
                .eq(ObjectUtils.isNotEmpty(status), TbOrder::getStatus, status)
        ;
        List<TbOrder> orderList = list(queryWrapper);
        return orderList;
    }

    @Override
    public String payOrder(Long orderId) {
        QueryWrapper<TbOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(ObjectUtils.isNotEmpty(orderId), TbOrder::getId, orderId)
                .eq(TbOrder::getStatus, OrderStatusEnum.WAIT_PAY.getCode())
        ;
        List<TbOrder> orderList = list(queryWrapper);
        if (CollectionUtils.isEmpty(orderList)) {
            return "待支付订单不存在";
        }
        List<TbOrder> newOrderList = new ArrayList<>();
        for (TbOrder order : orderList) {
            order.setStatus(OrderStatusEnum.PAID.getCode());
            newOrderList.add(order);
        }
        updateBatchById(newOrderList);
        if (ObjectUtils.isNotEmpty(orderId)) {
            log.info("订单：{}支付成功", orderId);
            return "订单：" + orderId + "支付成功";
        } else {
            log.info("所有订单支付成功");
            return "所有订单支付成功";
        }
    }

    @Override
    public String addStock(Long itemId, Integer count) {
        String itemStockKey = RedisConstant.ITEM_STOCK_KEY + ":" + itemId;
        redisTemplate.opsForValue().increment(itemStockKey, count);
        itemService.incrCountById(itemId, count);
        return "商品：" + itemId + "增加库存：" + count + "成功";
    }
}
